class Person(object):  # 类名---->大驼峰
    # __slots__ 是定义在class内的元组，表示该类可以存在哪些属性
    __slots__ = ('name', 'attack', 'defend', 'hp')

    # __init__在对象创建时会自动调用
    def __init__(self, name, attack, defend):  # 在__init__方法中定义属性
        # print('init {}'.format(self))
        self.name = name
        self.attack = attack
        self.defend = defend

    def run(self):
        print('running')

    def eat(self):
        print('eating')

    # __del__在对象销毁时自动调用
    def __del__(self):
        print('del')


p1 = Person('ax', 50, 3)
p2 = Person('tb', 56, 6)
p1.run()
p2.eat()

# p1 = Person('ax', 50, 3)
# step1:调用__new__申请内存空间
# step2:调用__init__方法并传入参数，将self指向这段内存空间
# step3:最后p1也指向这段内存空间


p1.hp = 1000  # py对象可以在类外添加属性
print('p1.hp = {}'.format(p1.hp))

# p1.mp = 340  py对象只能添加__slots__中存在的属性（无论在class内还是外）
# 当没有__slots__元组时，py对象可以随意添加属性

print('p1 is {}'.format(p1))  # 直接打印对象名，打印的是对象的地址


#  在直接打印对象时，其实是调用了__str__或__repr__
#  当二者同时存在时，调用__str__
#  __str__强调可读性，__repr__强调准确性

class Animal:
    def __repr__(self):
        return '__repr__'

    def __str__(self):
        return '__str__'


a1 = Animal()
print(a1)  # print(a1.__str__())
